<!--
 * @Descripttion: 动态表单渲染器
 * @version: 1.0
 * @Author: sakuya+tcy
 * @Date: 2024年3月22日09:26:25
 * @LastEditors:
 * @LastEditTime:
-->

<template>
  <!-- <el-skeleton v-if="renderLoading || Object.keys(form).length == 0" animated /> -->
  <el-form
    ref="formRef"
    :model="form"
    :label-width="config.labelWidth"
    :label-position="config.labelPosition"
    v-loading="loading"
    element-loading-text="Loading..."
  >
    <el-row :gutter="15">
      <slot name="content"></slot>
      <template v-for="(item, index) in config.formItems" :key="index">
        <el-col   :xs="24" :sm="24" :md="24" :lg="item.span || 24" :xl="item.span || 24">
          <sc-title
            v-if="item.component == 'title'"
            :title="item.label"
          ></sc-title>
          
          <el-form-item v-else :prop="item.name">
            <template #label>
                <span v-if="item.required" style="color: #f56c6c;margin-right: 4px;">*</span>
                <span style="display:inline-block;">{{ item.label }}</span>
            </template>
            <!-- input -->
            <!-- && item.pattern == 'simple' -->
            <template
              v-if="item.component == 'input' && item.pattern == 'simple'"
            >
              <el-input
                v-model="form[item.name]"
                :placeholder="item.placeholder"
                clearable
                :type="item.options.type"
                :maxlength="item.options.maxlength"
                show-word-limit
                :size="item.size"
                :disabled="item.disabled"
              >
              <template v-if="item.options.append" #append>{{ item.options.append }}</template>
            </el-input>
            </template>
            <!-- input range -->
            <!-- && item.pattern == 'complex' -->
            <template
              v-else-if="item.component == 'input' && item.pattern == 'complex'"
            >
              <el-row>
                <el-col :span="11">
                  <!-- operatorData. -->
                  <el-input
                    v-model="form[item.name.inputVaule1]"
                    :placeholder="item.placeholder"
                    clearable
                    :maxlength="item.options.maxlength"
                    show-word-limit
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-input>
                </el-col>
                <el-col :span="2"
                  ><span style="margin-left: 0.5rem">-</span></el-col
                >
                <el-col :span="11">
                  <!-- operatorData. -->
                  <el-input
                    v-model="form[item.name.inputVaule2]"
                    :placeholder="item.placeholder"
                    clearable
                    :maxlength="item.options.maxlength"
                    show-word-limit
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-input>
                </el-col>
              </el-row>
            </template>
            <!-- checkbox -->
            <template v-else-if="item.component == 'checkbox'">
              <template v-if="item.name">
                <el-checkbox
                  v-model="form[item.name][_item.name]"
                  :label="_item.label"
                  v-for="(_item, _index) in item.options.items"
                  :key="_index"
                  :size="item.size"
                  :disabled="item.disabled"
                ></el-checkbox>
              </template>
              <template v-else>
                <el-checkbox
                  v-model="form[_item.name]"
                  :label="_item.label"
                  v-for="(_item, _index) in item.options.items"
                  :key="_index"
                  :size="item.size"
                  :disabled="item.disabled"
                ></el-checkbox>
              </template>
            </template>
            <!-- checkboxGroup -->
            <template v-else-if="item.component == 'checkboxGroup'">
              <el-checkbox-group
                v-model="form[item.name]"
                :min="item.options.min"
                :max="item.options.max"
              >
                <el-checkbox
                  v-for="_item in item.options.items"
                  :key="_item.value"
                  :label="_item.value"
                  :size="item.size"
                  :disabled="item.disabled"
                  >{{ _item.label }}</el-checkbox
                >
              </el-checkbox-group>
            </template>
            <!-- upload -->
            <template v-else-if="item.component == 'upload'">
              <el-col
                v-for="(_item, _index) in item.options.items"
                :key="_index"
              >
                <el-form-item :prop="_item.name">
                  <sc-upload
                    v-model="form[_item.name]"
                    :title="_item.label"
                  ></sc-upload>
                </el-form-item>
              </el-col>
            </template>
            <!-- switch -->
            <template v-else-if="item.component == 'switchv'">
              <el-switch
                v-model="form[item.name]"
                :size="item.size"
                :disabled="item.disabled"
                :active-value="item.options.activeValue"
                :inactive-value="item.options.inactiveValue"
              />
            </template>
            <!-- select -->
            <template v-else-if="item.component == 'select'">
              <el-select
                v-model="form[item.name]"
                :multiple="
                  item.options.multiple ? item.options.multiple : false
                "
                :placeholder="item.placeholder ? item.placeholder : '请选择'"
                clearable
                filterable
                collapse-tags
                :max-collapse-tags="2"
                :size="item.size"
                :disabled="item.disabled"
                :multiple-limit="item.options.limit"
                style="width: 100%"
                @change="handleFieldChange"
              >
                <el-option
                  v-for="option in item.options.items"
                  :key="option.value"
                  :label="option.label"
                  :value="option.value"
                ></el-option>
              </el-select>
            </template>
            <!--treeSelect-->
            <template v-else-if="item.component == 'treeSelect'">
              <el-tree-select
                v-model="form[item.name]"
                :data="item.options.items"
                :check-strictly="item.options.checkStrictly"
                :multiple="item.options.multiple"
                :show-checkbox="item.options.showCheckbox"
                collapse-tags
                :max-collapse-tags="2"
                clearable
                :multiple-limit="item.options.limit"
                :size="item.size"
                @focus="treeSelectFocus(item)"
                :disabled="item.disabled"
              >
              </el-tree-select>
            </template>
            <!-- cascader -->
            <template v-else-if="item.component == 'cascader'">
              <el-cascader
                v-model="form[item.name]"
                :options="item.options.items"
                :props="getCascaderProps(item.options)"
                clearable
                collapse-tags
                :show-all-levels="false"
                filterable
                :max-collapse-tags="2"
                :size="item.size"
                :disabled="item.disabled"
              ></el-cascader>
            </template>

            <!-- date -->
            <template
              v-else-if="
                item.component == 'datePicker' && item.pattern == 'simple'
              "
            >
              <!-- :type="item.options.type"  -->
              <el-date-picker
                v-model="form[item.name]"
                :type="item.option.dateType"
                :shortcuts="item.options.shortcuts"
                :default-time="item.options.defaultTime"
                :value-format="item.options.valueFormat"
                :placeholder="item.placeholder || '请选择'"
                :size="item.size"
                :disabled="item.disabled"
              ></el-date-picker>
            </template>
            <!-- dataRange -->
            <template
              v-else-if="
                item.component == 'datePicker' && item.pattern == 'complex'
              "
            >
              <el-row>
                <el-col :span="4">
                  <el-select
                    v-model="form[item.name.operator]"
                    :placeholder="item.placeholder || '请选择'"
                    filterable
                    style="width: 100%"
                    @change="(value) => dataChange(value, item)"
                  >
                    <el-option
                      v-for="option in item.operatorData"
                      :key="option.value"
                      :label="option.label"
                      :value="option.value"
                      :size="item.size"
                      :disabled="item.disabled"
                    ></el-option>
                  </el-select>
                </el-col>
                <el-col :span="8" style="margin-left: 0.25rem">
                  <el-date-picker
                    v-model="form[item.name.startValue]"
                    :type="date"
                    :shortcuts="item.options.shortcuts"
                    value-format="YYYY-MM-DD"
                    :placeholder="item.placeholder || '请选择'"
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-date-picker>
                </el-col>
                <el-col :span="1"
                  ><span style="margin-left: 0.5rem"> - </span></el-col
                >
                <el-col :span="8">
                  <el-date-picker
                    v-model="form[item.name.endValue]"
                    :type="date"
                    :shortcuts="item.options.shortcuts"
                    value-format="YYYY-MM-DD"
                    :placeholder="item.placeholder || '请选择'"
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-date-picker>
                </el-col>
              </el-row>
            </template>
            <!-- number -->
            <template
              v-else-if="
                item.component == 'inputNumber' && item.pattern == 'simple'
              "
            >
              <el-input-number
                v-model="form[item.name]"
                controls-position="right"
                :size="item.size"
                :disabled="item.disabled"
                :min="item.options.min"
                :max="item.options.max"
                :step="item.options.step"
                :precision="item.options.precision"
              ></el-input-number>
            </template>
            <!-- number range -->
            <template
              v-else-if="
                item.component == 'inputNumber' && item.pattern == 'complex'
              "
            >
              <el-col :xs="14" :sm="6" :md="6">
                <el-select
                  v-model="form[item.name.operator]"
                  :placeholder="item.placeholder || '请选择'"
                  @change="changeInputNumber"
                  clearable
                  filterable
                  style="width: 100%"
                >
                  <el-option
                    v-for="option in item.operatorData"
                    :key="option.value"
                    :label="option.label"
                    :value="option.value"
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-option>
                </el-select>
              </el-col>
              <el-col :xs="24" :sm="10" :md="8">
                <el-input-number
                  v-model="form[item.name.startValue]"
                  controls-position="right"
                  :size="item.size"
                  :disabled="item.disabled"
                ></el-input-number>
              </el-col>
              <el-col :xs="24" :sm="10" :md="2" v-if="isShowEndInputNumber"
                ><span> 至 </span></el-col
              >
              <el-col :xs="24" :sm="10" :md="8" v-if="isShowEndInputNumber">
                <el-input-number
                  v-model="form[item.name.endValue]"
                  controls-position="right"
                  :size="item.size"
                  :disabled="item.disabled"
                ></el-input-number>
              </el-col>
            </template>
            <!-- radio -->
            <template v-else-if="item.component == 'radio'">
              <el-radio-group v-model="form[item.name]">
                <el-radio
                  v-for="_item in item.options.items"
                  :key="_item.value"
                  :label="_item.value"
                  >{{ _item.label }}</el-radio
                >
              </el-radio-group>
            </template>
            <!-- color -->
            <template v-else-if="item.component == 'color'">
              <el-color-picker v-model="form[item.name]" />
            </template>
            <!-- rate -->
            <template v-else-if="item.component == 'rate'">
              <el-rate
                style="margin-top: 6px"
                v-model="form[item.name]"
                :allow-half="item.options.allowHalf"
              ></el-rate>
            </template>
            <!-- slider -->
            <template v-else-if="item.component == 'slider'">
              <el-slider
                v-model="form[item.name]"
                :marks="item.options.marks"
              ></el-slider>
            </template>
            <!-- tableselect -->
            <template v-else-if="item.component == 'complexInputBox'">
              <tableselect-render
                v-model="form[item.name]"
                :item="item"
              ></tableselect-render>
            </template>
            <!-- editor -->
            <template v-else-if="item.component == 'editor'">
              <sc-editor
                v-model="form[item.name]"
                placeholder="请输入"
                :height="400"
              ></sc-editor>
            </template>
            <!--codeEditor-->
            <template v-else-if="item.component == 'codeEditor'">
            <ts-code-editor style="width: 100%;" v-model="form[item.name]" :height="item.options.height"></ts-code-editor>
          </template>
            <!-- noComponent -->
            <template v-else>
              <el-tag type="danger"
                >[{{ item.component }}] Component not found</el-tag
              >
            </template>
            <div v-if="item.message" class="el-form-item-msg">
              {{ item.message }}
            </div>
          </el-form-item>
        </el-col>
      </template>
      <slot name="footer"></slot>
    </el-row>
  </el-form>
</template>

<script setup>
import http from "@/utils/request";
import $time from "@/utils/time";
import Api from "@/api/model/system";
import tsCodeEditor from '@/components/scCodeEditor/index.vue'
import {
  defineAsyncComponent,
  onMounted,
  watch,
  ref,
  defineModel,
  computed,
} from "vue";
const tableselectRender = defineAsyncComponent(() =>
  import("./items/inputSelect")
);
const scEditor = defineAsyncComponent(() => import("@/components/scEditor"));
const props = defineProps({
  config: { type: Object, default: () => {} },
  loading: { type: Boolean, default: false },
  fileName: { type: String, default: "" },
});
const form = defineModel();
const formRef = ref(null);
const renderLoading = ref(false);
const isShowEndInputNumber = ref(true);
watch(
  () => props.config,
  () => {
    if (hasConfig.value) {
      render();
    }
  }
);
const hasConfig = computed(() => {
  return Object.keys(props.config).length > 0;
});
onMounted(() => {
  if (hasConfig.value) {
    render();
  }
});
const render = () => {
  props.config.formItems.forEach((item) => {
    if (item.component == "checkbox") {
      if (item.name) {
        const value = {};
        item.options.items.forEach((option) => {
          value[option.name] = option.value;
        });
        form.value[item.name] = value;
      } else {
        item.options.items.forEach((option) => {
          form.value[option.name] = option.value;
        });
      }
    } else if (item.component == "upload") {
      if (item.name) {
        const value = {};
        item.options.items.forEach((option) => {
          value[option.name] = option.value;
        });
        form.value[item.name] = value;
      } else {
        item.options.items.forEach((option) => {
          form.value[option.name] = option.value;
        });
      }
    } else if (item.component == "datePicker" && item.pattern == "complex") {
      form.value[item.name.operator] = item.value.operator;
      form.value[item.name.startValue] = item.value.startValue;
      form.value[item.name.endValue] = item.value.endValue;
    } else if (item.component == "inputNumber" && item.pattern == "complex") {
      form.value[item.name.operator] = item.value.operator;
      form.value[item.name.startValue] = item.value.startValue;
      form.value[item.name.endValue] = item.value.endValue;
    } else {
      if (form.value[item.name] == undefined) {
        form.value[item.name] = item.value;
      }
    }
  });
  getData();
};
//选择项远程数据加载
const getData = () => {
  renderLoading.value = true;
  var remoteData = [];
  props.config.formItems.forEach((item) => {
    if (item.options && item.options.remote) {
      var req = http
        .get(item.options.remote.api, item.options.remote.data)
        .then((res) => {
          item.options.items = res.data;
        });
      remoteData.push(req);
    }
  });
  Promise.all(remoteData).then(() => {
    renderLoading.value = false;
  });
};
const treeSelectFocus = async (item) => {
  if (item.options.items.length === 0) {
    let params = {
      fileName: item.options.dataset.fileName,
    };
    let res = await Api.select.query.post(params);
    if (res.code == "200") {
      item.options.items = res.reportData;
    }
  }
};
const validate = (valid, obj) => {
  return formRef.value.validate(valid, obj);
};
const dataChange = (val, item) => {
  if (
    item.component == "datePicker" &&
    item.pattern == "complex" &&
    val !== "between"
  ) {
    form.value[item.name.startValue] = $time.getDateRange(val)[0];
    form.value[item.name.endValue] = $time.getDateRange(val)[1];
  } else if (val == "between") {
    form.value[item.name.startValue] = "";
    form.value[item.name.endValue] = "";
  }
};
const changeInputNumber = (val) => {
  if (val == "between") {
    isShowEndInputNumber.value = true;
  } else {
    isShowEndInputNumber.value = false;
  }
};
//级联选择器配置
const getCascaderProps = (val) => {
  return {
    multiple: val.multiple,
    checkStrictly: val.checkStrictly,
  };
};
defineExpose({ validate });
</script>
<style></style>